package com.Java.train.business.service.daily.Impl;

import cn.hutool.core.date.DateUtil;
import com.Java.train.business.entity.*;
import com.Java.train.business.entity.DTO.TrainDTO;
import com.Java.train.business.service.SkTokenService;
import com.Java.train.business.service.TrainService;
import com.Java.train.business.service.daily.*;
import com.Java.train.common.response.CommonResp;
import com.Java.train.business.entity.DTO.DailyTrainDTO;
import com.Java.train.business.req.daily.DailyTrainQueryReq;
import com.Java.train.common.exception.BusniessException;
import com.Java.train.common.exception.BusniessExceptionEnum;
import com.Java.train.common.response.PageResp;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.Java.train.business.mapper.DailyTrainMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import com.Java.train.common.utils.SnowFlakeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.date.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
* 每日车次 服务实现类
*
* @author luomoxingchen
* @since 2024-09-24
*/
@Service
public class DailyTrainServiceImpl extends ServiceImpl<DailyTrainMapper, DailyTrain> implements DailyTrainService {

    private static final Logger LOG = LoggerFactory.getLogger(DailyTrainService.class);

    @Autowired
    DailyTrainMapper dailyTrainMapper;
    @Resource
    TrainService trainService;
    @Resource
    DailyTrainCarriageService dailyTrainCarriageService;
    @Resource
    DailyTrainStationService dailyTrainStationService;
    @Resource
    DailyTrainSeatService dailyTrainSeatService;
    @Resource
    DailyTrainTicketService dailyTrainTicketService;
    @Resource
    SkTokenService skTokenService;
     /**
      * @Description: 查询所有每日车次（含条件筛选）
      * @param
      * @return
      */
    @Override
    public PageResp<DailyTrainDTO> queryList(DailyTrainQueryReq dailyTrainQueryReq){
        // 1.获取当前用户id信息
        //        Long id = LoginMemberContext.getId();
        Date date = dailyTrainQueryReq.getDate();
        String trainCode = dailyTrainQueryReq.getCode();
        // 2.查询数据库中是否存在当前信息（id）
        LOG.info("查询页码：{}", dailyTrainQueryReq.getPage());
        LOG.info("每页条数：{}", dailyTrainQueryReq.getSize());
        PageHelper.startPage(dailyTrainQueryReq.getPage(),dailyTrainQueryReq.getSize());

        // 判重
        List<DailyTrain> dailyTrains = null;
        if(StrUtil.isNotBlank(trainCode) || ObjectUtil.isNotEmpty(date)){
            dailyTrains = getDailyTrainByCondition(trainCode, date);
        }else {
            dailyTrains = list();
        }

        if(dailyTrains == null || CollUtil.isEmpty(dailyTrains)){
            // 返回空列表
            return new PageResp<DailyTrainDTO>();
//            throw new BusniessException(BusniessExceptionEnum.MEMBER_PASSENGER_NOT_EXITS);
        }

        // 3 分析分页信息
        // 3.1 获取分页总条数和页数
        PageInfo<DailyTrain> pageInfo = new PageInfo<>(dailyTrains);
        LOG.info("总行数：{}", pageInfo.getTotal());
        LOG.info("总页数：{}", pageInfo.getPages());

        // 3.2 转为封装后的返回值并封装到分页返回值中
        List<DailyTrainDTO> list = BeanUtil.copyToList(dailyTrains, DailyTrainDTO.class);
        PageResp<DailyTrainDTO> pageResp = new PageResp<>();
        pageResp.setTotal(pageInfo.getTotal());
        pageResp.setList(list);
        // 4.返回查询到的信息
        return pageResp;
    }
     /**
      * @Description: 保存或修改每日车次数据
      * @param
      * @return
      */
    @Override
    public CommonResp<Object> modify(DailyTrain dailyTrain) {
        Long id = dailyTrain.getId();
        DateTime dateTime = DateTime.now();
        if(ObjectUtil.isNull(id)){
            // 查重
            DailyTrain TrainDB = getTrainByUnique(dailyTrain.getCode(), dailyTrain.getDate());
            if(ObjectUtil.isNotEmpty(TrainDB)){
                throw new BusniessException(BusniessExceptionEnum.BUSINESS_TRAIN_ALREADY_EXITS);
            }

            dailyTrain.setId(SnowFlakeUtil.getSnowFlakeNextId());
            dailyTrain.setCreateTime(dateTime);
            dailyTrain.setUpdateTime(dateTime);
            boolean save = save(dailyTrain);
            return new CommonResp<>(save);
        } else {
            dailyTrain.setUpdateTime(dateTime);
            boolean update = updateById(dailyTrain);
            return new CommonResp<>(update);
        }
    }
 /**
  * @Description: 删除每日数据
  * @param
  * @return
  */
    @Override
    public CommonResp<Object> remove(String ids) {
        if(StrUtil.isNotEmpty(ids)){
            String[] array = ids.split(",");
            if(!CollectionUtils.isEmpty(Arrays.asList(array))) {
                // 删除ids所有有关的信息
                DailyTrain train = getById(ids);
                String trainCode = train.getCode();
                dailyTrainStationService.remove(new LambdaQueryWrapper<DailyTrainStation>().eq(DailyTrainStation::getTrainCode, trainCode).eq(DailyTrainStation::getDate, train.getDate()));
                dailyTrainCarriageService.remove(new LambdaQueryWrapper<DailyTrainCarriage>().eq(DailyTrainCarriage::getTrainCode, trainCode).eq(DailyTrainCarriage::getDate, train.getDate()));
                dailyTrainSeatService.remove(new LambdaQueryWrapper<DailyTrainSeat>().eq(DailyTrainSeat::getTrainCode, trainCode).eq(DailyTrainSeat::getDate, train.getDate()));
                dailyTrainTicketService.remove(new LambdaQueryWrapper<DailyTrainTicket>().eq(DailyTrainTicket::getTrainCode, trainCode).eq(DailyTrainTicket::getDate, train.getDate()));
                return new CommonResp<>(dailyTrainMapper.deleteBatchIds(Arrays.asList(array)));
            }
        }
        return new CommonResp<>(Collections.EMPTY_LIST);
    }

     /**
      * @param
      * @Description: 根据日期生成每日车次数据（跑批任务）
      */
    @Override
    @Transactional
    public void genDaily(Date date) {
        // 1.查询是否存在火车
        List<TrainDTO> trainDTOS = trainService.queryAll();
        List<Train> trains = BeanUtil.copyToList(trainDTOS, Train.class);
        if(CollUtil.isEmpty(trains)){
            LOG.info("没有火车信息");
            throw new BusniessException(BusniessExceptionEnum.BUSINESS_TRAIN_NOT_EXITS);
        }

        // 2.复制生成dailyTrain
        for (Train train : trains) {
            // 2.1 删除之前生成的火车
            // 转换时间格式（方法默认是yyyy-MM-dd)
            LOG.info("生成日期为[{}]车次编号为[{}]的火车数据开始", DateUtil.formatDate(date), train.getCode());
            genDailyTrain(date, train);
            LOG.info("生成日期为[{}]车次编号为[{}]的火车数据结束", DateUtil.formatDate(date), train.getCode());
        }
    }
     /**
      * @Description: 根据日期删除之前并生成每日车次数据
      * @param
      * @return
      */
     @Transactional
    private void genDailyTrain(Date date, Train train) {
        // 1.删除已有的火车信息
        LambdaQueryWrapper<DailyTrain> wrapper = new LambdaQueryWrapper<>();
        remove(wrapper.eq(DailyTrain::getDate, date).eq(DailyTrain::getCode, train.getCode()));

        // 2.生成当前日期的每日火车信息
        DateTime dateTime = DateTime.now();
        DailyTrain dailyTrain = BeanUtil.copyProperties(train, DailyTrain.class);
        dailyTrain.setId(SnowFlakeUtil.getSnowFlakeNextId());
        dailyTrain.setCreateTime(dateTime);
        dailyTrain.setUpdateTime(dateTime);
        dailyTrain.setDate(date);
        save(dailyTrain);

        String trainCode = train.getCode();
        // 保存每日车厢信息
        dailyTrainCarriageService.genDaily(date, trainCode);
        // 生成每日车站信息
        dailyTrainStationService.genDaily(date, trainCode);
        // 生成每日车座信息
        dailyTrainSeatService.getDaily(date, trainCode);
        // 生成每日车票数据
         String trainType = train.getType();
        dailyTrainTicketService.genDaily(date, trainCode, trainType);

        // 生成对应列车的令牌信息
         skTokenService.genDaily(date, trainCode);
    }

     /**
      * @Description: 条件查询
      * @param
      * @return
      */
    // 通过唯一键校验查重
    private List<DailyTrain> getDailyTrainByCondition(String trainCode,  Date date) {
        LambdaQueryWrapper<DailyTrain> wrapper = new LambdaQueryWrapper<>();
        List<DailyTrain> list = null;
        if(StrUtil.isNotBlank(trainCode) && ObjectUtil.isEmpty(date)){
            list = list(wrapper.eq(DailyTrain::getCode, trainCode).orderBy(true, true, DailyTrain::getCode));
        } else if(ObjectUtil.isNotEmpty(date) && StrUtil.isBlank(trainCode)){
            list = list(wrapper.eq(DailyTrain::getDate, date).orderBy(true, true, DailyTrain::getDate));
        } else{
            // 先按车号，在按车号降序
            list = list(wrapper.eq(DailyTrain::getCode, trainCode).eq(DailyTrain::getDate, date).orderBy(true, true, DailyTrain::getDate, DailyTrain::getCode)
                    .orderBy(true, false, DailyTrain::getDate));
        }
        return list;
    }
     /**
      * @Description: 唯一键判重
      * @param
      * @return
      */
    // 通过唯一键校验查重
    private DailyTrain getTrainByUnique(String code, Date date) {
        LambdaQueryWrapper<DailyTrain> wrapper = new LambdaQueryWrapper<>();
        DailyTrain one = getOne(wrapper.eq(DailyTrain::getCode, code).eq(DailyTrain::getDate, date));
        return one;
    }


}


